#include "stdafx.h"
#include "FileDialogEx.h"

CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
  LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags,
  LPCTSTR lpszFilter, DWORD dwFilterIndex, HWND hWndParent)
{
  memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL
  m_szFileName[0] = _T('\0');
  m_szFileTitle[0] = _T('\0');

  m_bOpenFileDialog = bOpenFileDialog;
  m_ofn.lStructSize = sizeof(m_ofn);
  m_ofn.lpstrFile = m_szFileName;
  m_ofn.nMaxFile = _MAX_PATH * 100;
  m_ofn.lpstrDefExt = lpszDefExt;
  m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle;
  m_ofn.nMaxFileTitle = _MAX_FNAME;
  m_ofn.Flags = dwFlags | OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLESIZING | OFN_NOCHANGEDIR;
  m_ofn.lpstrFilter = lpszFilter;
  m_ofn.hwndOwner = hWndParent;
  m_ofn.nFilterIndex = dwFilterIndex;
  // setup initial file name
  if (lpszFileName != NULL)
    _tcscpy_s(m_szFileName, _countof(m_szFileName), lpszFileName);
}

CFileDialogEx::~CFileDialogEx()
{

}

INT_PTR CFileDialogEx::DoModal(HWND hWndParent /* = ::GetActiveWindow() */)
{
  if (m_ofn.hwndOwner == NULL)   // set only if not specified before
    m_ofn.hwndOwner = hWndParent;

  if (m_bOpenFileDialog)
    return ::GetOpenFileName(&m_ofn);
  else
    return ::GetSaveFileName(&m_ofn);
}

LPCTSTR CFileDialogEx::GetPathName() const
{
  return m_ofn.lpstrFile;
}

DWORD CFileDialogEx::GetFilterIndex() const
{
  return m_ofn.nFilterIndex;
}

POSITION CFileDialogEx::GetStartPosition() const
{
  return (POSITION)m_ofn.lpstrFile;
}

ATL::CString CFileDialogEx::GetNextPathName(POSITION& pos) const
{
  BOOL bExplorer = m_ofn.Flags & OFN_EXPLORER;
  TCHAR chDelimiter;
  if (bExplorer)
    chDelimiter = '\0';
  else
    chDelimiter = ' ';

  LPTSTR lpsz = (LPTSTR)pos;
  if (lpsz == m_ofn.lpstrFile) // first time
  {
    if ((m_ofn.Flags & OFN_ALLOWMULTISELECT) == 0)
    {
      pos = NULL;
      return m_ofn.lpstrFile;
    }

    // find char pos after first Delimiter
    while (*lpsz != chDelimiter && *lpsz != '\0')
      lpsz = _tcsinc(lpsz);
    lpsz = _tcsinc(lpsz);

    // if single selection then return only selection
    if (*lpsz == 0)
    {
      pos = NULL;
      return m_ofn.lpstrFile;
    }
  }

  CString strBasePath = m_ofn.lpstrFile;
  if (!bExplorer)
  {
    LPTSTR lpszPath = m_ofn.lpstrFile;
    while (*lpszPath != chDelimiter)
      lpszPath = _tcsinc(lpszPath);
    strBasePath = strBasePath.Left(int(lpszPath - m_ofn.lpstrFile));
  }

  LPTSTR lpszFileName = lpsz;
  CString strFileName = lpsz;

  // find char pos at next Delimiter
  while (*lpsz != chDelimiter && *lpsz != '\0')
    lpsz = _tcsinc(lpsz);

  if (!bExplorer && *lpsz == '\0')
    pos = NULL;
  else
  {
    if (!bExplorer)
      strFileName = strFileName.Left(int(lpsz - lpszFileName));

    lpsz = _tcsinc(lpsz);
    if (*lpsz == '\0') // if double terminated then done
      pos = NULL;
    else
      pos = (POSITION)lpsz;
  }

  TCHAR strDrive[_MAX_DRIVE], strDir[_MAX_DIR], strName[_MAX_FNAME], strExt[_MAX_EXT];
  Checked::tsplitpath_s(strFileName, strDrive, _MAX_DRIVE, strDir, _MAX_DIR, strName, _MAX_FNAME, strExt, _MAX_EXT);
  TCHAR strPath[_MAX_PATH];
  if (*strDrive || *strDir)
  {
    Checked::tcscpy_s(strPath, _countof(strPath), strFileName);
  }
  else
  {
    if ((strBasePath.GetLength() != 3) || (strBasePath[1] != ':') || (strBasePath[2] != '\\'))
    {
      strBasePath += _T("\\");
    }
    Checked::tsplitpath_s(strBasePath, strDrive, _MAX_DRIVE, strDir, _MAX_DIR, NULL, 0, NULL, 0);
    Checked::tmakepath_s(strPath, _MAX_PATH, strDrive, strDir, strName, strExt);
  }

  return strPath;
}
